import { RefBean, Selectable, RefBeanTreeNode } from '../models';


declare var langMap: any;
declare function unescape(str: any): any;
declare function escape(str: any): any;

export class Utils {
    /**
     *  把代码映射成字典表中的i18n值，如果代码为空，则返回代码为defaultKey的值，如果连defaultKey也找不到值，则返回代码本身，如果 代码为null或undefined则返回空串。
     * @param key 要映射的代码,或是RefBean，如果是RefBean，则以code为键。
     * @param dictMap 字典数据
     * @param defaultKey 缺省代码，可选参数，缺省为"-"
     */
    static lookup(key: any, dictMap: Object, defaultKey = "-"):string{
        let _key = key;
        if (key && key.code) {
            _key = key.code;
        }
        if (!_key) {
            _key = defaultKey;
        }
        if (dictMap) {
            let _val = dictMap[_key];
            if (_val) {
                return _val;
            }
        }
        if (key && key.name) {
            return key.name;
        }
        return _key;
    }
	/**
	 * 把Error Object中的错误消息解析出友好的消息
	 * @param err Error Object
	 * @return 友好的消息
	 */
	public static resolveJsonErrorMessage(err: any): string {
		let rn = "。";
		/* Spring MVC Sample: 
		 * 1.
		 * {
		 * "headers":{"normalizedNames":{},"lazyUpdate":null},
		 * "status":500,
		 * "statusText":"OK",
		 * "url":"http://localhost:8080/aiib-irmp-web/rest/iisp-job/job-items",
		 * "ok":false,
		 * "name":"HttpErrorResponse",
		 * "message":"Http failure response for http://localhost:8080/aiib-irmp-web/rest/iisp-job/job-items: 500 OK",
		 * "error":{"type":"RuntimeException","message":"Error occurred here."}}
		 * 2.
		 * {headers: HttpHeaders, status: 500, statusText: "Internal Server Error", 
			url: "http://localhost:8080/cgd-web/rest/iisp-access-log/logs?x=1&pageNumber=1&pageSize=20", 
			ok: false,
			"error":{"messageKey":"err.IISP_AUTH_ROLE_003","code":"IISP_AUTH_ROLE_003","localizedMessage":"要删除的角色不存在!","type":"I18nAppException","message":"Role not exists."}}"
			error: {code: "IISP_AUTH_ROLE_003"
				defaultMessage: "Default"
				localizedMessage: "要删除的角色不存在!"
				messageKey: "err.IISP_AUTH_ROLE_003"
				type: "I18nAppException"}
		} 
		3."{"headers":{"normalizedNames":{},"lazyUpdate":null},
		"status":503,
		"statusText":"Service Unavailable",
		"url":"http://localhost/ibm-graph-web/rest/iisp-base/dict/map/IISP_JOB_TYPE","ok":false,
		"name":"HttpErrorResponse",
		"message":"Http failure response for http://localhost/ibm-graph-web/rest/iisp-base/dict/map/IISP_JOB_TYPE: 503 Service Unavailable","error":"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>503 Service Unavailable</title>\n</head><body>\n<h1>Service Unavailable</h1>\n<p>The server is temporarily unable to service your\nrequest due to maintenance downtime or capacity\nproblems. Please try again later.</p>\n</body></html>\n"}"
		*/
		let msg = Utils.resolveLocalizedMessage("msg.errorOccurred");
		if (err.error && err.error.defaultMessage) {
			err = err.error;
			if (err.defaultMessage) {
				if (err.code) {
					msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorCode") + "：" + err.code;
				}
				if (err.localizedMessage) {
					msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorMessage") + "：" + err.localizedMessage;
				} else {
					msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorMessage") + "：" + err.defaultMessage;
				}
				if (err.cause) {
				    msg = msg + rn + Utils.resolveLocalizedMessage("msg.rootMessage") + "：" + err.cause;
			     }
				//Utils.showMessage(msg);
				return msg;
			}
		}
		if (err.localizedMessage) {
			msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorMessage") + "：" + err.localizedMessage;
		} else if (err.message) {
			msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorMessage") + "：" + err.message;
		} else {
		    msg = msg + rn + Utils.resolveLocalizedMessage("msg.errorMessage") + "：" + err;
		}
		if (err.status) {
			msg = msg + rn + Utils.resolveLocalizedMessage("msg.httpStatus") + err.status;
			//msg = msg + rn + Utils.resolveLocalizedMessage("msg.returnMessage") + err.statusText;
		}
		return msg;
	}
	static showMessage(msg: string): void {
		alert(msg);
	}
	static showMessageByKey(key: string): void {
		Utils.showMessage(Utils.resolveLocalizedMessage(key));
	}
	static cloneObject(src: Object, dist: Object): void {
		for (let prop in src) {
			dist[prop] = src[prop];
		}
	}
	/**根据key和参数，找到相应的语言标签 
	 * @param key the message key
	 * @param params parameters to replace the placeholder in message. If params is not an array, then treat it as the first parameter.
	 * @return resolved localized message. return the key if message not found.
	 */
	public static resolveLocalizedMessage(key: string, params?: string[]):string {
		let msg = langMap[key];
		if (msg == undefined) {
			return key;
		}
		if (params) {
			if (params.length) {
				for (let i = 0; i < params.length; i++) {
					msg = msg.replace("{" + i + "}", params[i]);
				}
			} else {
				msg = msg.replace("{0}", params);
			}
		}
		return msg;
	}
	/** 对比两个数组的内容是否一样.
	 * @param array1 数组1
	 * @param array2 数组2
	 * @param property 要比较的属性值
	 * @return true if same.
	 */
	public static compareArrays(array1: Array<any>, array2: Array<any>, property: string): boolean {
		if (array1.length != array2.length) {
			return false;
		}
		for (let i = 0; i < array1.length; i++) {
			let obj1 = array1[i];
			let found = false;
			for (let k = 0; k < array2.length; k++) {
				let obj2 = array2[k];
				if (property) {
					if (obj2[property] == obj1[property]) {
						found = true;
						break;
					}
				} else {
					if (obj2 == obj1) {
						found = true;
						break;
					}
				}
			}
			if (!found) {
				return false;
			}
		}
		return true;
	}


	/**  
	 * 取得当前数据日期   
	*/
	static getCurrentDataDate(): string {
		return Utils.getCookie("currentDataDate");
	}

	/**  
	 * 取得当前的一级机构号  
	*/
	static getCurrentNodeCode(): string {
		return Utils.getCookie("currentNodeCode");
	}
	/**  
	 * 取得指定的cookie变量值   
	*/
	static getCookie(name: string): any {
		let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); //正则匹配
		if (arr = document.cookie.match(reg)) {
			return unescape(arr[2]);
		}
		else {
			return null;
		}
	}
    /**  
     * 取得当前域名，如: baidu.com   
    */
	static getDomainName():string {
	    var names = document.domain.split('.');
	    if (names.length > 1) {
	        var dname = names[1];
	        for (var i = 2; i < names.length; i++) {
	            dname += '.' + names[i];
	        }
	        return dname;
	    }
	    return document.domain;
	}
    /**  
     * 设置指定的cookie变量值  
    */
	static setCookie1(name:string, value:string, path?:string, domain?:string, expries?: Date): void {
	    let cookieName = name + "=" + escape(value);
	    if (expries) {
	        cookieName += ";expries=" + expries;
	    }
	    if (path) {
	        cookieName += ";path=" + path;
	    }
	    if (domain) {
	        cookieName += ";domain=" + domain;
	    }
	    document.cookie = cookieName;
	}
	/**  
	 * 设置指定的cookie变量值以及有效时间（毫秒）
	*/
	static setCookie(name: string, value: string, msec?: number): void {
		let cs = name + '=' + escape(value);
		if (msec) {
			let exp = new Date();
			exp.setTime(exp.getTime() + msec * 1);
			cs += ";expires=" + exp.toUTCString();
		}
		document.cookie = cs;
	}
	/**  
	 * 删除指定的cookie变量
	*/
	static delCookie(name: string): void {
		let exp = new Date();
		exp.setTime(exp.getTime() - 1);
		let cval = Utils.getCookie(name);
		if (cval != null) {
			document.cookie = name + "=" + cval + ";expires=" + exp.toUTCString();
		}
	}
	/**  
	 * 获取可选取列表中选中的项目
	 * @param array 可选项目列表
	 * @param property 返回的选中项目属性，如列表是TreeNode类型，而要返回的选中项可能是TreeNode.data,那么porperty就应该是“data”，如果不提供porperty，将返回列表中选中的TreeNode。
	*/
	static getSelectedBeans(array: Selectable[], property?: string): any[] {
		let rst = new Array<any>();
		for (let s of array) {
			if (s.isSelected) {
				if (property) {
					rst.push(s[property]);
				} else {
					rst.push(s);
				}
			}
		}
		return rst;
	}
	/**  
	 * 格式化数字显示方式   
	 * 用法  
	 * formatNumber(12345.999,'#,##0.00');  
	 * formatNumber(12345.999,'#,##0.##');  
	 * formatNumber(123,'000000');  
	 * @param num  要格式化的数字
	 * @param pattern  想要的格式
	 */
	static formatNumber(num: number, pattern: string): string {
		let strarr = num ? num.toString().split('.') : ['0'];
		let fmtarr = pattern ? pattern.split('.') : [''];
		let retstr = '';

		// 整数部分   
		let str = strarr[0];
		let fmt = fmtarr[0];
		let i = str.length - 1;
		let comma = false;
		for (let f = fmt.length - 1; f >= 0; f--) {
			switch (fmt.substr(f, 1)) {
				case '#':
					if (i >= 0) retstr = str.substr(i--, 1) + retstr;
					break;
				case '0':
					if (i >= 0) retstr = str.substr(i--, 1) + retstr;
					else retstr = '0' + retstr;
					break;
				case ',':
					comma = true;
					retstr = ',' + retstr;
					break;
			}
		}
		if (i >= 0) {
			if (comma) {
				let l = str.length;
				for (; i >= 0; i--) {
					retstr = str.substr(i, 1) + retstr;
					if (i > 0 && ((l - i) % 3) == 0) retstr = ',' + retstr;
				}
			}
			else retstr = str.substr(0, i + 1) + retstr;
		}

		retstr = retstr + '.';
		// 处理小数部分   
		str = strarr.length > 1 ? strarr[1] : '';
		fmt = fmtarr.length > 1 ? fmtarr[1] : '';
		i = 0;
		for (let f = 0; f < fmt.length; f++) {
			switch (fmt.substr(f, 1)) {
				case '#':
					if (i < str.length) retstr += str.substr(i++, 1);
					break;
				case '0':
					if (i < str.length) retstr += str.substr(i++, 1);
					else retstr += '0';
					break;
			}
		}
		return retstr.replace(/^,+/, '').replace(/\.$/, '');
	}
	/**
	 * 将日期串转换成日期类型的变量
	 * @param dateStr 日期串，支持如2018-10-31, 20181031, 31/10/2018等格式
	 * 
	 */
	static parseDate(dateStr: string): Date {
		if (dateStr.length == 8) {
			//yyyyMMdd格式
			let year = parseInt(dateStr.substr(0, 4));
			let month = parseInt(dateStr.substr(4, 2));
			let day = parseInt(dateStr.substr(6, 2));
			return new Date(year, month - 1, day);
		}
		//其它格式
		return new Date(dateStr);
	}
	/**
	 * 将日期按照指定的格式格式化成字符串用于显示
	 * @param date 日期
	 * @param fmt 想要的格式，如：“yyyy-MM-dd hh:mm:ss S”, “yyyy年第q季度”
	 */
	static formatDate(date: Date, fmt: string): string {
		var o = {
			"M+": date.getMonth() + 1,                 //月份   
			"d+": date.getDate(),                    //日   
			"h+": date.getHours(),                   //小时   
			"m+": date.getMinutes(),                 //分   
			"s+": date.getSeconds(),                 //秒   
			"q+": Math.floor((date.getMonth() + 3) / 3), //季度   
			"S": date.getMilliseconds()             //毫秒   
		};
		if (/(y+)/.test(fmt))
			fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
		for (var k in o)
			if (new RegExp("(" + k + ")").test(fmt))
				fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
		return fmt;
	}
	/**
	 * 获取请求参数的值，如var=1，则返回"1"
	 * @param name 参数名
	 */
	static getParameter(name: string): string {
        let val = location.search.match(new RegExp("[\?\&]" + name + "=([^\&]+)", "i"));
        if (val && val.length > 0) {
            return decodeURI(val[1]);
        }
		return null;
	};
    /**
     * 获取同名多个请求参数的值数组，如var=1&var=2,返回["1","2"]
     * @param name 参数名
     */
	static getParameterValues( name: string ): string[] {
        let rsts: string[] = location.search.match( new RegExp( "[\?\&]" + name + "=([^\&]+)", "g" ) );
        if ( rsts && rsts.length > 0 ) {
            let vals = new Array( rsts.length );
            for ( let i = 0; i < rsts.length; i++ ) {
                vals[i] = decodeURI(rsts[i].substring( rsts[i].indexOf( "=" ) + 1 ) );
            }
            return vals;
        }
        return null;
    };
	
}